t2linux-config: Sync the hardware clock at shutdown - #55
Closed
josemiguelo wants to merge 1 commit into
Closed
Conversation
T2 Macs have one real RTC, in the EC, exposed to Linux twice: rtc0 through the legacy CMOS ports and rtc1 through the ACPI Time and Alarm Device. Only _SRT on the ACPI side actually writes it. The kernel's 11-minute NTP writeback targets the hctosys device, rtc0, and the firmware discards those writes into a volatile shadow that reads back correctly and then forgets on reboot. Nothing therefore ever sets the clock. Every boot reads a counter ticking since the last cold power-on (1970-01-28), systemd bumps that to its own build date, and the machine runs weeks in the past until chrony syncs. Journal timestamps are wrong on every boot, and PackageKit's reboot-to-install offline updates abort before rpm opens the database, because that boot has no network to correct the clock first. Add a oneshot unit that writes system time to the ACPI TAD RTC at shutdown. rtc0 reads the same EC clock, so hctosys picks the value up on the next boot. The RTC is located by ACPI000E in its name rather than hardcoded to rtc1, and the unit is a no-op on machines without one. Tested on MacBookPro16,1 (Fedora 44, kernel 7.1.9-200.t2): the boot log goes from "setting system clock to 1970-01-28T03:04:49 UTC" to the correct time, and an offline update that had failed twice completes.
Collaborator
|
This a known issue. Rebooting to macos will fix the rtc so we don't need hacks. A kernel module (macsmc/t2smc) is also in development that will permanently fix this. If you don't want to reboot to macos, you can blacklist the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
t2linux-config: sync the hardware clock at shutdown
The problem
Every T2 Mac boots with a wrong clock. On a MacBookPro16,1 running Fedora 44:
1970-01-28is not garbage — it is a counter that has been ticking accurately since the last coldpower-on (the deltas between boots match wall-clock time exactly). systemd then bumps the clock
forward to its own build-date epoch, so the machine runs weeks in the past until chrony syncs.
Most of the time nobody notices, because NTP corrects it seconds after the desktop appears. Anything
running before the network does not get that:
journalctl -b -1actively misleading when debugging
system-update.targetwithno network, so the clock is never corrected before the transaction runs. On my machine the
transaction aborted after 6 seconds with an empty error the dnf5 backend logged nowhere, and
/var/lib/rpm/rpmdb.sqlitewas never touched — it died before rpm opened the database. It failedtwice, and Discover simply re-offered the same packages after each reboot.
Root cause
These machines have exactly one real, battery-backed RTC, and it lives in the EC. It is exposed to
Linux twice:
rtc0hctosysreads at boot; writes are discardedrtc1\_SB.PCI0.LPCB.ARTC(ACPI000E)_SRTis the only write that persistsThere is no
PNP0B00anywhere in the ACPI namespace — Apple never declares a legacy CMOS RTC — sortc0is the x86 fallback stub (platform rtc_cmos: registered fallback platform RTC device) thathappens to alias the EC clock.
The kernel's 11-minute NTP writeback targets the
hctosysdevice, which isrtc0. Those writes landin a volatile shadow: they read back correctly, so
timedatectlreports the right RTC time andeverything looks healthy, but the firmware re-initialises that shadow from the EC's own clock on the
next boot and the value is gone.
So the EC clock has simply never been set on any of these machines. The hardware was always capable
of keeping time; nothing ever wrote to the one interface that stores it.
The fix
A oneshot unit that writes system time through the ACPI TAD at shutdown.
rtc0reads the same ECclock, so
hctosyspicks the value up on the next boot with no further help.The RTC is located by
ACPI000Ein/sys/class/rtc/*/namerather than hardcoded tortc1, sinceenumeration order is not guaranteed, and the unit is a no-op on any machine without such a device.
Scope / risk
_SRTis the firmware's own documented setter, the same one macOS uses, and it doesnot touch the alarm registers.
local-fs.target, so it cannot delay boot or interfere with anythingduring normal operation.
acpi_tad's set path works on the stock kernel — see the note below.ACPI000ERTC is present theExecStoploop finds nothing and exits 0.Verification
On MacBookPro16,1, Fedora 44,
kernel-7.1.9-200.t2.fc44. Before:After writing the clock through
rtc1and rebooting:That was the first boot on this machine whose journal was not stamped 1970/epoch.
The offline update then succeeded on the next attempt, same 14 packages, same cached RPMs, same
backend:
dnf5 historyrecords transaction 80 asStatus: Ok, 14 upgrades and 14 replaced, no scriptleterrors. The earlier run died in 6 seconds before rpm started; this one spent two and a half minutes
actually installing.
Notes for reviewers
This is verified on one model. Everything above is a MacBookPro16,1. The ACPI path and EC layout
could differ on other T2 machines. Looking the device up by
ACPI000Erather than by path or numbershould cover that, and the unit no-ops where there is no such device, but I cannot claim "all T2
Macs" without someone else's hardware. Confirmation on another model would be welcome — the check is
just
journalctl -b -k | grep "setting system clock to"before and after.Shutdown-only is deliberate, but debatable. The EC clock keeps ticking on its own, so it stays
correct between writes and a single write at shutdown is enough to keep drift negligible. Someone who
only ever suspends would go a long time between syncs. Happy to add a timer or an
ExecStartorderedafter
time-sync.targetif you would rather have belt and braces.There is a cleaner long-term fix, kernel-side. Reading
rtc1currently fails with-EIO: Apple's_GRTfills the ACPI validity byte (offset 7) from an EC field its own DSDT declares asPAD0andnever sets, so
acpi_taddiscards a perfectly good timestamp. Only the read path checks that byte,which is why setting the clock works on a stock kernel and this unit needs no patch.
With that quirk fixed, plus making the TAD the
hctosysdevice, the kernel's own boot-time read and11-minute writeback would handle all of this natively and this unit could be dropped. That is a
larger change and I did not want it to block a working userspace fix, but I have the
acpi_tadpatchwritten and tested if there is interest in carrying it in
linux-t2-patchesalongside an upstreamsubmission.
How to confirm this on your own machine
Nothing here changes anything on your system.
1. What clock did the kernel read at boot?
Affected:
Any date that isn't roughly today means the RTC has never been set. The exact value will differ from
mine — it is a counter running since your last cold power-off, so a machine that has been powered for
three days reads about
1970-01-04.Not affected: the line shows the current date, or there is no such line at all.
2. Confirm the two-RTC layout.
Affected:
rtc0is the x86 fallback stub, and it is the devicehctosysreads.rtc1is the ACPI TAD, the onethat can actually be written. Your numbering may differ — what matters is that an
ACPI000Edeviceexists and is not the
hctosys=1one.3. Do not use
timedatectlto check.The kernel's writes to
rtc0land in a volatile shadow that reads back correctly and is discarded onreboot. This is why the bug is easy to miss: at runtime everything looks healthy. Only the boot-time
value in step 1 tells the truth.
Verify the fix on your model — before the package ships
This is the two-minute test, and it needs no patched kernel and no new package. Using the
ACPI000Edevice from step 2:
If the boot line now shows the correct date instead of 1970, the fix works on your hardware. That is
exactly what this unit automates. Reports from models other than MacBookPro16,1 would be very useful.
Verify after installing the package
Stopping the oneshot runs its
ExecStop, so you can trigger the write without waiting for a realshutdown:
Then reboot — a reboot is the only real proof, since the runtime reads are correct either way:
Fixed looks like:
and every row of
--list-bootscarries a real timestamp instead of all of them starting at the samewrong date (systemd's build-date epoch).
Two things I deliberately built in: the timedatectl warning, because a reviewer checking that way will conclude their machine is fine and the report is wrong; and the hwclock --rtc=/dev/rtc1 --systohc + reboot test, which lets someone on a different T2 model validate the whole premise in two minutes without building or installing anything. That's the most direct answer to the "verified on one model" caveat.